<?php
class experiment_module extends abstract_module implements adminable{
	public function __construct() {
		parent::__construct();
	}

	public function execute($action = "", &$param = null) {
		parent::execute($action);

		$options = options::get_instance();

		switch ($action) {
			case EXPERIMENT_ACTION_CANCEL:
				if (!auth_user::get_instance()->is_logged()) return false;
				return $this->action_cancel();
			case EXPERIMENT_ACTION_NEW_SEQUENCE_EXPERIMENT:
				if (!auth_user::get_instance()->is_logged()) return false;
				$this->action_new_sequence_experiment();
				break;
			case EXPERIMENT_ACTION_NEW_CHAIN_EXPERIMENT:
				if (!auth_user::get_instance()->is_logged()) return false;
				$this->action_new_chain_experiment();
				break;
			case EXPERIMENT_ACTION_CONTINUE:
				if (!auth_user::get_instance()->is_logged()) return false;
				$this->action_continue();
				break;
			case EXPERIMENT_ACTION_ANALYSIS:
				if (!auth_user::get_instance()->is_logged()) return false;
				$this->action_analysis();
				break;
			case EXPERIMENT_ACTION_NEXT_STEP:
				if (!auth_user::get_instance()->is_logged()) return false;
				return $this->action_next_step(&$param);
			case EXPERIMENT_ACTION_ADD_OBJECT_TYPE:
				if (!auth_user::get_instance()->is_logged()) return false;
				return $this->action_add_object_type(&$param);
			case EXPERIMENT_ACTION_ADD_OBJECT_TYPE_FOR_CHAIN:
				if (!auth_user::get_instance()->is_logged()) return false;
				return $this->action_add_object_type_for_chain();
			case EXPERIMENT_ACTION_ADD_OBJECT_TYPE_FOR_SEQUENCE:
				if (!auth_user::get_instance()->is_logged()) return false;
				return $this->action_add_object_type_for_sequence();
			case EXPERIMENT_ACTION_ADD_OBJECT:
				if (!auth_user::get_instance()->is_logged()) return false;
				return $this->action_add_object(&$param);
			case EXPERIMENT_ACTION_ADD_SEQUENCE:
				if (!auth_user::get_instance()->is_logged()) return false;
				return $this->action_add_sequence(&$param);
			case EXPERIMENT_ACTION_ADD_CHAIN:
				if (!auth_user::get_instance()->is_logged()) return false;
				return $this->action_add_chain(&$param);
			case EXPERIMENT_ACTION_ADD_BUTTON:
				if (!auth_user::get_instance()->is_logged()) return false;
				return $this->action_add_button(&$param);
			case EXPERIMENT_ACTION_ADD_TO_TABLE:
				if (!auth_user::get_instance()->is_logged()) return false;
				return $this->action_add_to_table(&$param);
			case EXPERIMENT_ACTION_ADD_ITEM:
				if (!auth_user::get_instance()->is_admin()) return false;
				$this->action_add_item();
				break;
			case EXPERIMENT_ACTION_ADD_NEW_SEQUENCE_DONE:
				if (!auth_user::get_instance()->is_admin()) return false;
				return $this->action_add_new_sequence_done(&$param);
			case EXPERIMENT_ACTION_SEQUENCES_LIST:
				if (!auth_user::get_instance()->is_admin()) return false;
				$this->action_sequence_list();
				break;
			case EXPERIMENT_ACTION_DELETE_SEQUENCE:
				if (!auth_user::get_instance()->is_admin()) return false;
				$this->action_delete();
				break;
			default:
				return false;
		}
		return true;
	}

	public static function get_adminable_actions() {
		$out = array();
		$out[] = new adminable_action_wrapper(EXPERIMENT_ACTION_SEQUENCES_LIST, "Sequences list");
		return $out;
	}

	private function action_delete() {
		$id = request::get_from_request("id", false, true);

		if ($id) {
			$sequence = new sequence($id);
			db_adapter::get_instance()->delete($sequence);
		}

		utils::redirect(url::get($this->module, EXPERIMENT_ACTION_SEQUENCES_LIST, array(), false));
	}
	private function action_sequence_list() {
		$ord_by = request::get_from_request("ord_by", "sequence_id", true);
		$ord_dir = request::get_from_request("ord_dir", "asc", true);

		$paginate_id = $this->module . $this->action;

		smarty_paginate_ex::connect($paginate_id, $_REQUEST);
		smarty_paginate_ex::set_limit(global_config::get_instance()->get_paginate_limit($this->module, $this->action), $paginate_id);

		$sequences = new object_composition();
		$list = db_adapter::get_instance()->get_composite_list($sequences, new query_criteria(), $total, smarty_paginate_ex::get_current_index($paginate_id), smarty_paginate_ex::get_limit($paginate_id), $ord_by, $ord_dir);

		smarty_paginate_ex::set_total($total, $paginate_id);
		$params = array('ord_by' => $ord_by, 'ord_dir' => $ord_dir);
		smarty_paginate_ex::set_url(url::get($this->module, $this->action, $params, false), $paginate_id);

		$tpl = new admin_page($this->action, $this->module);

		$tpl->assign_by_ref("sequences", $list);
		$tpl->assign("params", compact("ord_by", "ord_dir"));

		smarty_paginate_ex::assign($tpl, "paginate", $paginate_id);

		$tpl->display("sequences_list.tpl");
	}

	private function action_cancel() {
		utils::redirect(url::get());
	}

	private function action_new_sequence_experiment() {
		$tpl = new common_page($this->module, $this->action);
		$_SESSION['sequence_count'] = 0;
		$tpl->display("new_sequence_experiment.tpl");
	}

	private function action_new_chain_experiment() {
		$tpl = new common_page($this->module, $this->action);
		$_SESSION['chain_count'] = 0;
		$tpl->display("new_chain_experiment.tpl");
	}

	private function action_next_step($form) {
		$response = new xajaxResponse();
		$response->clear("process", "innerHTML");
		$tpl = new simple_page($this->module, $this->action);
		$response->assign("process", "innerHTML", $tpl->fetch("process.tpl"));
		$sclient = new client($form);

		return $response;
	}

	private function action_add_item() {
		$tpl = new admin_page($this->action, $this->module);

		$dba = db_adapter::get_instance();

		$obj_type = new object_type();
		$obj = new object();
		$file_type = new file_type();

		$obj_list = $dba->get_list($obj);

		$obj_type_list = $dba->get_list($obj_type);

		$file_type_list = $dba->get_list($file_type);

		$tpl->assign_by_ref("obj_list", $obj_list);
		$tpl->assign_by_ref("file_type_list", $file_type_list);
		$tpl->assign_by_ref("obj_type_list", $obj_type_list);

		$tpl->display("add_item.tpl");
	}

	private function action_add_object_type() {
		$response = new xajaxResponse();
		$tpl = new simple_page($this->module, $this->action);

		$dba = db_adapter::get_instance();

		$obj_type = new object_type();

		$obj_type_list = $dba->get_list($obj_type);
		$tpl->assign_by_ref("obj_type_list", $obj_type_list);

		if 	($_SESSION["experiment_type"]=="chain") {
			if ($_SESSION["chain_count"]==0){
				$chain_characteristic = new chain_characteristic_type();
				$chain_characteristic_list = $dba->get_list($chain_characteristic,new query_criteria());
				$tpl->assign_by_ref("characteristic",$chain_characteristic_list);
				$response->assign("table", "innerHTML", $tpl->fetch("chain_table.tpl"));}
		}

		if 	($_SESSION["experiment_type"]=="sequence") {
			if ($_SESSION["sequence_count"]==0){
				$response->assign("table", "innerHTML", $tpl->fetch("sequence_table.tpl"));}
		}
		$response->assign("add_to_table", "innerHTML", $tpl->fetch("add_object_type.tpl"));

		return $response;
	}

	private function action_add_object_type_for_chain() {
		$_SESSION["experiment_type"]="chain";
		$_SESSION["sequence_count"]=0;
		return $this->action_add_object_type();
	}
	private function action_add_object_type_for_sequence() {
		$_SESSION["experiment_type"]="sequence";
		$_SESSION["chain_count"]=0;
		return $this->action_add_object_type();
	}

	private function action_add_object($step2) {
		$response = new xajaxResponse();
		if (isset($step2["Object_type_list"])) {
			$response->clear("add_sequence", "innerHTML");
			$response->clear("button", "innerHTML");
			$dba = db_adapter::get_instance();

			$obj = new object();
			$tpl = new simple_page($this->module, $this->action);

			$criteria = new query_criteria();
			$criteria->add_criterion($obj->object_type_id, criterion_type::$equal, $step2);

			$obj_list = $dba->get_list($obj,$criteria);

			$tpl->assign_by_ref("obj_list", $obj_list);
			$response->assign("add_object", "innerHTML", $tpl->fetch("add_object.tpl"));

			return $response;
		} else {
			$response->clear("add_object", "innerHTML");
			$response->clear("add_sequence", "innerHTML");
			$response->clear("button", "innerHTML");
			return $response;
		}

	}

	private function action_add_sequence($step3) {

		$response = new xajaxResponse();
		if (isset($step3["sequences_list"])) {
			$response->clear("button", "innerHTML");
			$dba = db_adapter::get_instance();
			$sequen= new sequence_composition();
			$tpl = new simple_page($this->module, $this->action);

			$criteria = new query_criteria();
			$criteria->add_criterion_composite($sequen->sequence,$sequen->sequence->object_id, criterion_type::$equal, $step3);

			$sequence_list = $dba->get_composite_list($sequen,$criteria);
			$tpl->assign_by_ref("sequence_list", $sequence_list);
			if ($_SESSION['experiment_type']=="sequence") {
				$response->assign("add_sequence", "innerHTML", $tpl->fetch("add_sequence.tpl"));
			}
			if ($_SESSION['experiment_type']=="chain") {
				$response->assign("add_sequence", "innerHTML", $tpl->fetch("add_chain.tpl"));
			}

			return $response;
		} else {
			$response->clear("add_sequence", "innerHTML");
			$response->clear("button", "innerHTML");
			return $response;
		}

	}
	private function action_add_chain($seq_id) {
		$response = new xajaxResponse();

		if (!empty($seq_id)) {
			$response->clear("button", "innerHTML");
			$dba = db_adapter::get_instance();
			$chain= new chain();
			$tpl = new simple_page($this->module, $this->action);

			$criteria = new query_criteria();
			$criteria->add_criterion($chain->sequence_id, criterion_type::$equal, $seq_id);

			$chain_list = $dba->get_list($chain,$criteria);
			$tpl->assign_by_ref("chain_list", $chain_list);
			$response->assign("chains", "innerHTML", $tpl->fetch("chains.tpl"));

			return $response;
		} else {
			$response->clear("chains", "innerHTML");
			$response->clear("button", "innerHTML");
			return $response;
		}

	}

	private function action_add_to_table($id) {
		//TODO: paginate/ Del row/Libo bez classa no s pagenaitom libo snim no bez pagenata/udalenie odinakovih
		$response = new xajaxResponse();
		$response->clear("add_to_table", "innerHTML");

		$tpl = new simple_page($this->module, $this->action);
		if ($_SESSION['experiment_type']=="chain"){
			//TODO: для чейна доблявяется экшен с выпадением окна
			$_SESSION['chain_count']++;
			$characteristic_composition = new characteristic_characteristic_type_composition();

			$criteria = new query_criteria();
			$criteria->add_criterion_composite($characteristic_composition->chain_characteristic,$characteristic_composition->chain_characteristic->chain_id,criterion_type::$equal,$id);
			$dba = db_adapter::get_instance();
			$characteristic_list = $dba->get_composite_list($characteristic_composition,$criteria);
			$characteristic = $characteristic_list->get_next(false,true);
			$template_array = array();
			while (!empty($characteristic))
			{
				$tpl_name = $characteristic->chain_characteristic_type->chain_characteristic_type_description->get_value();
				$tpl_value = $characteristic->chain_characteristic->start_value->get_value();
				$template_array[$tpl_name] = $tpl_value;
				$characteristic = $characteristic_list->get_next(false,true);
			}
			
				$chain_characteristic = new chain_characteristic_type();
				$chain_characteristic_list = $dba->get_list($chain_characteristic);
				$tpl->assign_by_ref("template_array",$template_array);
				$tpl->assign_by_ref("characteristic",$chain_characteristic_list);

			
			
			$tpl->assign_by_ref("chain_id", $id);
			$chain_count = 'chain_count'. $_SESSION['chain_count'];
			$tpl->assign_by_ref("chain_count", $chain_count);
			$response->append("chain_table", "innerHTML", $tpl->fetch("add_to_chain_table.tpl"));
			return $response;
		}
		if ($_SESSION['experiment_type']=="sequence"){
			$_SESSION['sequence_count']++;
			$sequence_composition = new sequence_composition();

			$criteria = new query_criteria();
			$criteria->add_criterion_composite($sequence_composition->sequence,$sequence_composition->sequence->sequence_id,criterion_type::$equal,$id);
			$dba = db_adapter::get_instance();
			$dba->load_composite($sequence_composition,$criteria);

			$sequence_object_type = new sequence_object_type($id);
			$criteria->reset_criteria();
			$criteria->add_criterion_composite($sequence_object_type->sequence,$sequence_object_type->sequence->sequence_id,criterion_type::$equal,$id);
			$dba->load_composite($sequence_object_type,$criteria);
			$tpl->assign_by_ref("sequence", $sequence_object_type);
			$tpl->assign_by_ref("sequence_name", $sequence_composition->files->file_name->get_value());
			$tpl->assign_by_ref("sequence_id", $id);
			$sequence_count = 'sequence_count'. $_SESSION['sequence_count'];
			$tpl->assign_by_ref("sequence_count", $sequence_count);
			$response->append("sequence_table", "innerHTML", $tpl->fetch("add_to_sequence_table.tpl"));
			return $response;
		}
	}

	private function action_add_button($step4) {
		$response = new xajaxResponse();
		if ($_SESSION['experiment_type'] =="sequence"){
			if (!empty($step4)) {
				$tpl = new simple_page($this->module, $this->action);
				$response->assign("button", "innerHTML", $tpl->fetch("sequence_button.tpl"));
				return $response;
			} else {
				$response->clear("button", "innerHTML");
			}
			return $response;
		}
		if ($_SESSION['experiment_type'] =="chain"){
			if (!empty($step4)) {
				$tpl = new simple_page($this->module, $this->action);
				$response->assign("button", "innerHTML", $tpl->fetch("chain_button.tpl"));
				return $response;
			} else {
				$response->clear("button", "innerHTML");
			}
			return $response;
		}
	}


	private function action_continue() {
		$tpl = new common_page($this->module, $this->action);
		$tpl->display("continue.tpl");

	}
		private function action_analysis() {
		$tpl = new common_page($this->module, $this->action);
		$_SESSION['chain_count'] = 0;
		
		$dba = db_adapter::get_instance();
		
		$chain_characteristic = new chain_characteristic_type();
		$chain_characteristic_list = $dba->get_list($chain_characteristic,new query_criteria());
		$tpl->assign_by_ref("characteristic",$chain_characteristic_list);
				
		$tpl->display("analysis.tpl");

	}
	

	private function _validate_add_item($form) {
		$errors = error_logger::get_instance();
		if (empty($form['new_sequence_object_type_name'])) {
			$errors->add("Object type can not be empty");
		}

		if (empty($form['new_sequence_object_name'])) {
			$errors->add("Object can not be empty");
		}

		if (empty($form['new_file_name'])) {
			$errors->add("File name can not be empty");
		}
		if (empty($form['file_type_list'])) {
			$errors->add("Please choose file type name ");
		}
		if (empty($form['new_sequence_text'])) {
			$errors->add("Please enter sequence");
		}
	}

	private function action_add_new_sequence_done($form) {
		$response = new xajaxResponse();
		$response->clear("errors", "innerHTML");
		$errors = error_logger::get_instance();
		$this->_validate_add_item($form);

		if ($errors->count()) {
			$tpl = new simple_page($this->module, $this->action);
			$tpl->assign_by_ref("error_logger", $errors);
			$response->assign("errors", "innerHTML", $tpl->fetch("errors_wrapper.tpl"));
			return $response;
		}
		$dba = db_adapter::get_instance();
		$criteria = new query_criteria();

		$obj_type = new object_type();
		$criteria->add_criterion($obj_type->object_type_name, criterion_type::$equal, $form["new_sequence_object_type_name"]);
		if(!$dba->load($obj_type, $criteria)){
			$obj_type->object_type_name->set_value($form['new_sequence_object_type_name']);
			$obj_type->object_type_description->set_value($form['new_sequence_object_type_description']);
			$dba->save($obj_type);

			$dba->load($obj_type, $criteria);
		}

		$criteria->reset_criteria();
		$obj = new object();

		$criteria->add_criterion($obj->object_name, criterion_type::$equal, $form["new_sequence_object_name"]);
		$criteria->add_criterion($obj->object_type_id, criterion_type::$equal, $obj_type->object_type_id->get_value());

		if(!$dba->load($obj, $criteria)){
			$obj->object_name->set_value($form['new_sequence_object_name']);
			$obj->object_type_id->set_value($obj_type->object_type_id->get_value());
			$obj->object_description->set_value($form['new_sequence_object_description']);
			$dba->save($obj);

			$dba->load($obj, $criteria);
		}

		$criteria->reset_criteria();

		$file_type = new file_type();

		$criteria->add_criterion($file_type->file_type_name, criterion_type::$equal, $form["file_type_list"]);
		$dba->load($file_type, $criteria);

		$criteria->reset_criteria();
		$file = new files();

		$criteria->add_criterion($file->file_name, criterion_type::$equal, $form["new_file_name"]);
		$criteria->add_criterion($file->file_type_id, criterion_type::$equal, $file_type->file_type_id->get_value());

		if(!$dba->load($file, $criteria)){
			$file->file_name->set_value($form['new_file_name']);
			$file->file_type_id->set_value($file_type->file_type_id->get_value());
			$file->file_description->set_value($form['new_sequence_description']);
			$file->file_file->set_value($form['new_sequence_text']);
			$dba->save($file);

			$dba->load($file, $criteria);
		}

		$criteria->reset_criteria();
		$sequence = new sequence();

		$criteria->add_criterion($sequence->file_id, criterion_type::$equal, $file->file_id->get_value());
		$criteria->add_criterion($sequence->object_id, criterion_type::$equal, $obj->object_id->get_value());

		if(!$dba->load($sequence, $criteria)){
			$sequence->file_id->set_value($file->file_id->get_value());
			$sequence->object_id->set_value($obj->object_id->get_value());
			$dba->save($sequence);

		}

		$tpl = new simple_page($this->module, $this->action);
		$response->assign("errors", "innerHTML", $tpl->fetch("new_sequence_saved_successfuly.tpl"));
		return $response;
	}
}
?>
